/*
Esempio 6.
lettura di una soluzione da file ed estrazione dei valori utili a generare vincoli
per il problema di seprazione


il file "soluzione" contiene:
nella prima riga il numero di nodi e archi del grafo associato
una riga per ogni variabile (associata ad ogni arco del grafo) contenente una stringa nel formato "coda testa valore_sol"
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "glpk.h"

void itoa(int, char[]);
void reverse(char[]);

int main(void) {

	/* Definizione delle strutture */
	glp_prob *lp;
	int i,n,e,v1,v2,ia[1+1000], ja[1+1000],offset_coeff,offset_constr;
	double x,ar[1+1000];
	FILE* fp;
	char varname[15], aux[5],constraintname[15];
	
	
	// Inizializzazione variabili
	strcpy(varname, "z_");
	strcpy(aux, "");
	strcpy(constraintname, "");
	
	// Creazione del problema in memoria e assegnazione di un nome mnemonico
	lp = glp_create_prob();
	glp_set_prob_name(lp, "Problema seprazione");
	
	// Tipologia del problema
	glp_set_obj_dir(lp, GLP_MAX);
	
	
	fp = fopen("soluzione", "r");
	// TODO controlli fp == null
	
	fscanf(fp,"%d %d\n",&n,&e); // la prima riga contiene numero di nodi e archi del grafo associato a questa soluzione

	// Aggiunta delle righe del problema (una coppia per arco più uno)
	glp_add_rows(lp, (2*e)+1);	
	// Aggiunta delle colonne del problema (una per arco più una per nodo)
	glp_add_cols(lp, n+e);
	
	for(i = 1; i <=n; i++){
		// qui possiamo generare le variabili z_i
		itoa(i, aux);
		strcat(varname, aux);
		glp_set_col_name(lp, i, varname);
		glp_set_col_bnds(lp, i, GLP_DB, 0.0, 1.0);
		
		// qui possiamo aggiungere in f.o. -z_i
		glp_set_obj_coef(lp, i, -1.0);
		
		strcpy(varname, "z_");
	}
	printf("%d %d\n",n,e);
	
	
	strcpy(varname, "w_");
	offset_coeff = 1;	// numero ordinale di coefficiente che stiamo inserendo (parte dal primo)
	offset_constr = 1;	// numero ordinale del vincolo che stiamo inserendo (parte dal primo)
	// Lettura righe
	for (i = 1; i <= e ; i++){		
		fscanf(fp,"%d %d %lf\n",&v1,&v2,&x); // le righe successive contengono le variabili nella notazione "coda testa valore_sol"
		// in questa riga varname == "w_"
		itoa(v1, aux);
		strcat(varname, aux);
		// in questa riga varname == "w_v1"
		strcat(varname, "_");
		// in questa riga varname == "w_v1_"
		itoa(v2, aux);
		strcat(varname, aux);
		// in questa riga varname == "w_v1_v2"
		
		//	a questo punto possiamo generare la variabile w_v1_v2		
		glp_set_col_name(lp, n+i, varname);  // n+i esima perchè abbiamo creato n variabili z_i
		glp_set_col_bnds(lp, n+i, GLP_DB, 0.0, 1.0);
		//	a questo punto possiamo generare il vincolo w_v1_v2 - z_v1 <= 0
		ia[offset_coeff] = offset_constr;
		ja[offset_coeff] = n+i;	// w_v1_v2 è la n+i esima variabile
		ar[offset_coeff] = 1.0;
		offset_coeff++;	//abbiamo inserito un coefficiente della matrice
		
		ia[offset_coeff] = offset_constr;
		ja[offset_coeff] = v1; // z_v1 è la v1 esima variabile perchè sono state create in ordine
		ar[offset_coeff] = -1.0;
		offset_coeff++; //abbiamo inserito un coefficiente della matrice
		
		strcpy(constraintname,varname);
		strcat(constraintname,"-1");
		glp_set_row_name(lp, offset_constr, constraintname);
		glp_set_row_bnds(lp, offset_constr, GLP_UP, 0.0, 0.0);	// <= 0
		offset_constr++;	//abbiamo inserito un constraint
		
		//	a questo punto possiamo generare il vincolo w_v1_v2 - z_v2 <= 0
		ia[offset_coeff] = offset_constr;
		ja[offset_coeff] = n+i;	// w_v1_v2 è la n+i esima variabile
		ar[offset_coeff] = 1.0;
		offset_coeff++;	//abbiamo inserito un coefficiente della matrice
		
		ia[offset_coeff] = offset_constr;
		ja[offset_coeff] = v2; // z_v2 è la v2 esima variabile perchè sono state create in ordine
		ar[offset_coeff] = -1.0;
		offset_coeff++; //abbiamo inserito un coefficiente della matrice
		
		strcpy(constraintname,varname);
		strcat(constraintname,"-2");
		glp_set_row_name(lp, offset_constr, constraintname);
		glp_set_row_bnds(lp, offset_constr, GLP_UP, 0.0, 0.0);	// <= 0
		offset_constr++;	//abbiamo inserito un constraint
		
		//	a questo punto possiamo aggiungere in f.o. x * w_v1_v2
		glp_set_obj_coef(lp, n+i, x);
		
		printf("%d %d %lf\n",v1,v2,x);
		strcpy(varname,"w_");
	}
	
	//qui possiamo generare il vincolo z_qualcheindiceacazzo = 1
	
	fclose(fp);
	
	glp_load_matrix(lp, offset_coeff-1, ia, ja, ar);
	glp_write_lp(lp, NULL, "separazione.lp");
		
	glp_delete_prob(lp);
	return 0;
	
}

void itoa(int n, char s[])
 {
     int i, sign;
 
     if ((sign = n) < 0)  /* record sign */
         n = -n;          /* make n positive */
     i = 0;
     do {       /* generate digits in reverse order */
         s[i++] = n % 10 + '0';   /* get next digit */
     } while ((n /= 10) > 0);     /* delete it */
     if (sign < 0)
         s[i++] = '-';
     s[i] = '\0';
     reverse(s);
 }

void reverse(char s[])
 {
     int i, j;
     char c;
 
     for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
         c = s[i];
         s[i] = s[j];
         s[j] = c;
     }
 }
